﻿using System;
using System.Collections.Generic;
using System.Linq;

using System.Data;
using Prodma.DataAccess.Database;
using Prodma.DataAccess.Interfaces.Models;
using Prodma.DataAccess.Models.ViewModels;
using Prodma.DataAccess.Repositories;
using Prodma.DataAccess.Helper.Enumerators;
using System.Configuration;
//using Prodma.DataAccess.Portal.DataService.ListService;

namespace Prodma.DataAccess.DataService
{
    public class ContentService : IContentRepository
    {

        private DataContext context = new DataContext();
        
        private int defaultArchiveId;
        public ContentService()
        {
            defaultArchiveId = Convert.ToInt32(ConfigurationManager.AppSettings["defaultArchive"]);
        }

        #region IContentRepository Members

        public IList<int> GetCategoryList()
        {
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from content in context.tb_Content
                            where content.tb_Archive.Id == defaultArchiveId
                            group content by content.tb_Category.Id into category
                            select category.Key).ToList();

                return list;
            }
        }
        #endregion

        #region IRecordOperation<tb_Content,ContentVm> Members

        public IList<ContentVm> GetList()
        {
            throw new NotImplementedException();
        }

        public void New(tb_Content entity)
        {
            DataContext context = new DataContext();
            using (context)
            {
                context.AddTotb_Content(entity);
                context.SaveChanges();
            }
        }
        public ContentVm Edit(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var edit = (from content in context.tb_Content
                            where content.Id == id
                            select new ContentVm()
                            {
                                Id = content.Id,
                                Name = content.Name,
                                Title = content.Title,
                                Description = content.Description,
                                Content = content.Content,
                                Date = content.Date,
                                Folder = content.Folder,
                                Image = content.Image,
                                ImageOriginal = content.ImageOriginal,
                                Archive = new ArchiveVm() { Id = content.tb_Archive.Id, Name = content.tb_Archive.Name, Folder = content.tb_Archive.Folder },
                                Category = new CategoryVm() { Id = content.tb_Category.Id, Name = content.tb_Category.Name },
                                SDate = content.SDate.Value,
                                FDate = content.FDate.Value,
                                Language = new LanguageVm() { Id = content.tb_Language.Id, Name = content.tb_Language.Name },
                                State = new StateVm() { Id = content.tb_State.Id, Name = content.tb_State.Name }
                            }).FirstOrDefault();

                return edit;
            }
        }
        public void Update(int id, tb_Content entity)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var edit = (from content in context.tb_Content
                            where content.Id == id
                            select content).FirstOrDefault();

                edit.Name = entity.Name;
                edit.Title = entity.Title;
                edit.Description = entity.Description;
                edit.Content = entity.Content;
                edit.Date = DateTime.Now;
                edit.Folder = entity.Folder;
                edit.Image = entity.Image;
                edit.ImageOriginal = entity.ImageOriginal;
                edit.tb_ArchiveReference.EntityKey = entity.tb_ArchiveReference.EntityKey;
                edit.tb_CategoryReference.EntityKey = entity.tb_CategoryReference.EntityKey;
                edit.SDate = entity.SDate;
                edit.FDate = entity.FDate;
                edit.Date = entity.Date;
                edit.tb_LanguageReference.EntityKey = entity.tb_LanguageReference.EntityKey;
                edit.tb_StateReference.EntityKey = entity.tb_StateReference.EntityKey;

                context.SaveChanges();
            }
        }
        public void Delete(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var delete = (from content in context.tb_Content
                              where content.Id == id
                              select content).FirstOrDefault();

                context.DeleteObject(delete);
                context.SaveChanges();
            }
        }
        #endregion

        #region IPageOperation<ContentVm> Members

        public IList<ContentVm> GetList(int page)
        {
            int limitValue = Convert.ToInt32(ConfigurationManager.AppSettings["dataPagerLimit"]);
            int skipValue = page * limitValue;

            DataContext context = new DataContext();
            using (context)
            {
                var list = (from content in context.tb_Content
                            where content.tb_Archive.Id == defaultArchiveId
                            join order in context.tb_ContentOrder
                                on content.Id equals order.Content
                            select new ContentVm()
                            {
                                Id = content.Id,
                                Name = content.Name,
                                Archive = new ArchiveVm() { Id = content.tb_Archive.Id, Name = content.tb_Archive.Name },
                                Category = new CategoryVm() { Id = content.tb_Category.Id, Name = content.tb_Category.Name },
                                SDate = content.SDate.Value,
                                FDate = content.FDate.Value,
                                Order = new ContentOrderVm() { OrderNo = order.OrderNo },
                                Language = new LanguageVm() { Id = content.tb_Language.Id, Name = content.tb_Language.Name },
                                State = new StateVm() { Id = content.tb_State.Id, Name = content.tb_State.Name }
                            }).OrderByDescending(x => x.Order.OrderNo).Skip(skipValue).Take(limitValue).ToList();

                return list;
            }
        }
        #endregion

        #region IPageableFindOperation<ContentVm> Members

        public IList<ContentVm> GetList(int page, Dictionary<string, string> find)
        {
            int limitValue = Convert.ToInt32(ConfigurationManager.AppSettings["dataPagerLimit"]);
            int skipValue = page * limitValue;

            string findName = find["name"];
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from content in context.tb_Content
                            join order in context.tb_ContentOrder
                                on content.Id equals order.Content
                            where content.Name.StartsWith(findName) &&
                                  content.tb_Archive.Id == defaultArchiveId
                            select new ContentVm()
                            {
                                Id = content.Id,
                                Name = content.Name,
                                Archive = new ArchiveVm() { Id = content.tb_Archive.Id, Name = content.tb_Archive.Name },
                                Category = new CategoryVm() { Id = content.tb_Category.Id, Name = content.tb_Category.Name },
                                SDate = content.SDate.Value,
                                FDate = content.FDate.Value,
                                Order = new ContentOrderVm() { OrderNo = order.OrderNo },
                                Language = new LanguageVm() { Id = content.tb_Language.Id, Name = content.tb_Language.Name },
                                State = new StateVm() { Id = content.tb_State.Id, Name = content.tb_State.Name }
                            }).OrderByDescending(x => x.Order.OrderNo).Skip(skipValue).Take(limitValue).ToList();

                return list;
            }
        }
        public int GetTotalRowCount(Dictionary<string, string> find)
        {
            string findName = find["name"];
            DataContext context = new DataContext();
            using (context)
            {
                int rowCount = (from content in context.tb_Content
                                where content.Name.StartsWith(findName) &&
                                      content.tb_Archive.Id == defaultArchiveId
                                select content).Count();

                return rowCount;
            }
        }
        #endregion

        #region IParentRelationshipOperation Members

        public IList<int> GetCounts()
        {
            DataContext context = new DataContext();
            using (context)
            {
                var countList = (from content in context.tb_Content
                                 where content.tb_Archive.Id == defaultArchiveId
                                 group content by content.tb_Category.Id into category
                                 select category.Count()).ToList();

                return countList;
            }
        }
        public IList<int> GetCounts(string find)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var countList = (from content in context.tb_Content
                                 where content.Name.StartsWith(find) &&
                                       content.tb_Archive.Id == defaultArchiveId
                                 group content by content.tb_Category.Id into category
                                 select category.Count()).ToList();

                return countList;
            }
        }
        #endregion

        #region IOrderOperation<ContentOrderVm> Members

        public void OrderUp(int id, ContentOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var currentOrder = (from order in context.tb_ContentOrder
                                    where order.Content == viewModel.Content &&
                                          order.tb_Archive.Id == viewModel.Archive &&
                                          order.tb_Category.Id == viewModel.Category &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                var nextOrder = (from order in context.tb_ContentOrder
                                 where order.OrderNo > viewModel.OrderNo &&
                                       order.tb_Archive.Id == viewModel.Archive &&
                                       order.tb_Category.Id == viewModel.Category
                                 select order).OrderBy(x => x.OrderNo).FirstOrDefault();

                if (nextOrder != null)
                {
                    nextOrder.OrderNo--;
                    currentOrder.OrderNo++;
                }

                context.SaveChanges();
            }
        }
        public void OrderDown(int id, ContentOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var currentOrder = (from order in context.tb_ContentOrder
                                    where order.Content == viewModel.Content &&
                                          order.tb_Archive.Id == viewModel.Archive &&
                                          order.tb_Category.Id == viewModel.Category &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                var previousOrder = (from order in context.tb_ContentOrder
                                     where order.OrderNo < viewModel.OrderNo &&
                                           order.tb_Archive.Id == viewModel.Archive &&
                                           order.tb_Category.Id == viewModel.Category
                                     select order).OrderByDescending(x => x.OrderNo).FirstOrDefault();

                if (previousOrder != null)
                {
                    previousOrder.OrderNo++;
                    currentOrder.OrderNo--;
                }

                context.SaveChanges();
            }
        }
        public void SetOrder(int id, ContentOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var lastOrder = (from order in context.tb_ContentOrder
                                 where order.tb_Archive.Id == viewModel.Archive &&
                                       order.tb_Category.Id == viewModel.Category
                                 select order).OrderByDescending(x => x.OrderNo).Take(1).FirstOrDefault();

                if (viewModel.SetOrderNo > lastOrder.OrderNo || viewModel.SetOrderNo <= 0)
                {
                    return;
                }

                var currentOrder = (from order in context.tb_ContentOrder
                                    where order.Content == viewModel.Content &&
                                          order.tb_Archive.Id == viewModel.Archive &&
                                          order.tb_Category.Id == viewModel.Category &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                int setOrderNo = (lastOrder.OrderNo - viewModel.SetOrderNo) + 1;
                int fark = setOrderNo - currentOrder.OrderNo;
                int oldCurrentOrder = currentOrder.OrderNo;
                currentOrder.OrderNo = setOrderNo;

                if (fark > 0)
                {
                    var nextOrder = (from order in context.tb_ContentOrder
                                     where order.OrderNo > oldCurrentOrder &&
                                           order.OrderNo <= setOrderNo &&
                                           order.tb_Archive.Id == viewModel.Archive &&
                                           order.tb_Category.Id == viewModel.Category
                                     select order).OrderBy(x => x.OrderNo).ToList();

                    foreach (tb_ContentOrder m in nextOrder)
                    {
                        m.OrderNo--;
                        context.SaveChanges();
                    }
                }
                else if (fark <= 0)
                {
                    var previousOrder = (from order in context.tb_ContentOrder
                                         where order.OrderNo < oldCurrentOrder &&
                                               order.OrderNo >= setOrderNo &&
                                               order.tb_Archive.Id == viewModel.Archive &&
                                               order.tb_Category.Id == viewModel.Category
                                         select order).OrderBy(x => x.OrderNo).ToList();

                    foreach (tb_ContentOrder m in previousOrder)
                    {
                        m.OrderNo++;
                        context.SaveChanges();
                    }
                }

                context.SaveChanges();
            }
        }
        #endregion

        #region IRowCountOperation Members

        public int GetTotalRowCount()
        {
            DataContext context = new DataContext();
            using (context)
            {
                int rowCount = (from content in context.tb_Content
                                where content.tb_Archive.Id == defaultArchiveId
                                select content).Count();

                return rowCount;
            }
        }
        public int GetTotalRowCount(int category)
        {
            DataContext context = new DataContext();
            using (context)
            {
                int rowCount = (from content in context.tb_Content
                                where content.tb_Archive.Id == defaultArchiveId &&
                                      content.tb_Category.Id == category
                                select content).Count();

                return rowCount;
            }
        }
        #endregion

        #region IStateOperation Members

        public void SetActive(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var viewState = (from content in context.tb_Content
                                 where content.Id == id
                                 select content).FirstOrDefault();

                viewState.tb_StateReference.EntityKey = new EntityKey("DataContext.tb_State", "Id", Convert.ToInt32(State.Active));

                context.SaveChanges();
            }
        }
        public void SetPassive(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var viewState = (from content in context.tb_Content
                                 where content.Id == id
                                 select content).FirstOrDefault();

                viewState.tb_StateReference.EntityKey = new EntityKey("DataContext.tb_State", "Id", Convert.ToInt32(State.Passive));

                context.SaveChanges();
            }
        }
        #endregion

        #region IImageOperation Members

        public void RemoveImage(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var removeImage = (from content in context.tb_Content
                                   where content.Id == id
                                   select content).FirstOrDefault();

                removeImage.Image = ConfigurationManager.AppSettings["contentBlankImage"].ToString();
                removeImage.ImageOriginal = ConfigurationManager.AppSettings["contentBlankImage"].ToString();

                context.SaveChanges();
            }
        }
        #endregion


        #region IContentRepository Members

        public IList<ContentVm> GetList(int page, int category)
        {
            int limitValue = Convert.ToInt32(ConfigurationManager.AppSettings["dataPagerLimit"]);
            int skipValue = page * limitValue;
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from content in context.tb_Content
                            where content.tb_Archive.Id == defaultArchiveId &&
                                  content.tb_Category.Id == category
                            join order in context.tb_ContentOrder
                                on content.Id equals order.Content
                            select new ContentVm()
                            {
                                Id = content.Id,
                                Name = content.Name,
                                Archive = new ArchiveVm() { Id = content.tb_Archive.Id, Name = content.tb_Archive.Name },
                                Category = new CategoryVm() { Id = content.tb_Category.Id, Name = content.tb_Category.Name },
                                SDate = content.SDate.Value,
                                FDate = content.FDate.Value,
                                Order = new ContentOrderVm() { OrderNo = order.OrderNo },
                                Language = new LanguageVm() { Id = content.tb_Language.Id, Name = content.tb_Language.Name },
                                State = new StateVm() { Id = content.tb_State.Id, Name = content.tb_State.Name }
                            }).OrderByDescending(x => x.Order.OrderNo).Skip(skipValue).Take(limitValue).ToList();

                return list;
            }
        }
        public void SetDefaultArchive(int id)
        {
            ConfigurationManager.AppSettings["defaultArchive"] = id.ToString();
        }

        #endregion

    }
}
